home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / danvbp / stindex.frm (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1994-04-28  |  23.8 KB  |  604 lines

  1. VERSION 2.00
  2. Begin Form Indexer 
  3.    BackColor       =   &H00C0C0C0&
  4.    Caption         =   "Stock Indexer"
  5.    ClientHeight    =   4905
  6.    ClientLeft      =   1095
  7.    ClientTop       =   1785
  8.    ClientWidth     =   8565
  9.    Height          =   5595
  10.    Left            =   1035
  11.    LinkTopic       =   "Form1"
  12.    ScaleHeight     =   4905
  13.    ScaleWidth      =   8565
  14.    Top             =   1155
  15.    Width           =   8685
  16.    Begin Timer tmr_Background 
  17.       Enabled         =   0   'False
  18.       Interval        =   2
  19.       Left            =   8040
  20.       Top             =   2640
  21.    End
  22.    Begin CommandButton cmd_Draw 
  23.       Caption         =   "Draw"
  24.       Height          =   435
  25.       Left            =   6780
  26.       TabIndex        =   14
  27.       Top             =   2640
  28.       Width           =   1035
  29.    End
  30.    Begin Frame Frame1 
  31.       BackColor       =   &H00FFFF00&
  32.       Caption         =   "Display Characteristic"
  33.       Height          =   1635
  34.       Left            =   4740
  35.       TabIndex        =   11
  36.       Top             =   3240
  37.       Width           =   3735
  38.       Begin Label lbl_DisplayState 
  39.          BackStyle       =   0  'Transparent
  40.          Caption         =   "State Machine Off"
  41.          Height          =   615
  42.          Left            =   60
  43.          TabIndex        =   13
  44.          Top             =   960
  45.          Width           =   3615
  46.       End
  47.       Begin Label lbl_DisplayChar 
  48.          BackColor       =   &H00FFFF00&
  49.          Height          =   555
  50.          Left            =   60
  51.          TabIndex        =   12
  52.          Top             =   300
  53.          Width           =   3615
  54.       End
  55.    End
  56.    Begin ListBox lst_Companies 
  57.       Height          =   2370
  58.       Left            =   6240
  59.       MultiSelect     =   2  'Extended
  60.       TabIndex        =   10
  61.       Top             =   180
  62.       Width           =   2115
  63.    End
  64.    Begin OptionButton opt_CurIndex 
  65.       BackColor       =   &H00C0C0C0&
  66.       Caption         =   "Index8"
  67.       ForeColor       =   &H00FFFFFF&
  68.       Height          =   315
  69.       Index           =   7
  70.       Left            =   4740
  71.       TabIndex        =   2
  72.       Top             =   2700
  73.       Width           =   1335
  74.    End
  75.    Begin OptionButton opt_CurIndex 
  76.       BackColor       =   &H00C0C0C0&
  77.       Caption         =   "Index7"
  78.       ForeColor       =   &H00FFFFFF&
  79.       Height          =   315
  80.       Index           =   6
  81.       Left            =   4740
  82.       TabIndex        =   9
  83.       Top             =   2340
  84.       Width           =   1335
  85.    End
  86.    Begin OptionButton opt_CurIndex 
  87.       BackColor       =   &H00C0C0C0&
  88.       Caption         =   "Index6"
  89.       ForeColor       =   &H00FFFFFF&
  90.       Height          =   315
  91.       Index           =   5
  92.       Left            =   4740
  93.       TabIndex        =   8
  94.       Top             =   1980
  95.       Width           =   1335
  96.    End
  97.    Begin OptionButton opt_CurIndex 
  98.       BackColor       =   &H00C0C0C0&
  99.       Caption         =   "Index5"
  100.       ForeColor       =   &H00FFFFFF&
  101.       Height          =   315
  102.       Index           =   4
  103.       Left            =   4740
  104.       TabIndex        =   7
  105.       Top             =   1620
  106.       Width           =   1335
  107.    End
  108.    Begin OptionButton opt_CurIndex 
  109.       BackColor       =   &H00C0C0C0&
  110.       Caption         =   "Index4"
  111.       ForeColor       =   &H00FFFFFF&
  112.       Height          =   315
  113.       Index           =   3
  114.       Left            =   4740
  115.       TabIndex        =   6
  116.       Top             =   1260
  117.       Width           =   1335
  118.    End
  119.    Begin OptionButton opt_CurIndex 
  120.       BackColor       =   &H00C0C0C0&
  121.       Caption         =   "Index3"
  122.       ForeColor       =   &H00FFFFFF&
  123.       Height          =   315
  124.       Index           =   2
  125.       Left            =   4740
  126.       TabIndex        =   5
  127.       Top             =   900
  128.       Width           =   1335
  129.    End
  130.    Begin OptionButton opt_CurIndex 
  131.       BackColor       =   &H00C0C0C0&
  132.       Caption         =   "Index2"
  133.       ForeColor       =   &H00FFFFFF&
  134.       Height          =   315
  135.       Index           =   1
  136.       Left            =   4740
  137.       TabIndex        =   4
  138.       Top             =   540
  139.       Width           =   1335
  140.    End
  141.    Begin OptionButton opt_CurIndex 
  142.       BackColor       =   &H00C0C0C0&
  143.       Caption         =   "Index1"
  144.       ForeColor       =   &H00FFFFFF&
  145.       Height          =   315
  146.       Index           =   0
  147.       Left            =   4740
  148.       TabIndex        =   3
  149.       Top             =   180
  150.       Value           =   -1  'True
  151.       Width           =   1335
  152.    End
  153.    Begin PictureBox pic_Display 
  154.       Height          =   4515
  155.       Left            =   60
  156.       ScaleHeight     =   4485
  157.       ScaleMode       =   0  'User
  158.       ScaleWidth      =   4485
  159.       TabIndex        =   0
  160.       Top             =   360
  161.       Width           =   4515
  162.    End
  163.    Begin Label Label1 
  164.       BackStyle       =   0  'Transparent
  165.       Caption         =   "Historical Data"
  166.       Height          =   195
  167.       Left            =   60
  168.       TabIndex        =   1
  169.       Top             =   60
  170.       Width           =   2475
  171.    End
  172.    Begin Menu mnu_Behave 
  173.       Caption         =   "Category"
  174.       Begin Menu mnu_Category 
  175.          Caption         =   "Non-Interruptable"
  176.          Checked         =   -1  'True
  177.          Index           =   0
  178.       End
  179.       Begin Menu mnu_Category 
  180.          Caption         =   "Background Display Only"
  181.          Index           =   1
  182.       End
  183.       Begin Menu mnu_Category 
  184.          Caption         =   "Background Display and Scaling"
  185.          Index           =   2
  186.       End
  187.    End
  188. Option Explicit
  189. Dim CurrentStateMachine%   ' Indicates which state machine is currently selected.
  190.                         ' 0 = Non-interruptable
  191.                         ' 1 = Background display
  192.                         ' 2 = Background display and scaling
  193. Dim CurrentSelectedIndex%   ' Index that is currently selected for editing.
  194. Dim Sheet As Object     ' Object will refer to Excel sheet
  195.                         ' containing stock prices.
  196. Dim Companies As Object ' Object refers to an Excel range
  197.                         ' containing the list of companies.
  198. Dim period As Object    ' Object refers to an Excel range
  199.                         ' containing the periods for which
  200.                         ' we have data.
  201. Dim HighRange As Object, LowRange As Object ' Range information
  202. Dim DataTable As Object ' Object refers to an Excel range
  203.                         ' containing all of the data for all
  204.                         ' of the companies.
  205. Dim IndexList$()    ' Brute force array of companies in
  206.                         ' each index.
  207. ' Used for fast listbox update
  208. Const WM_USER = &H400
  209. Const LB_FINDSTRINGEXACT = (WM_USER + 35)
  210. Const LB_SELITEMRANGE = (WM_USER + 28)
  211. Declare Function SendMessage& Lib "User" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, lParam As Any)
  212. Declare Function SendMessageBynum& Lib "User" Alias "SendMessage" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, ByVal lParam&)
  213. Declare Function SendMessageBystring& Lib "User" Alias "SendMessage" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, ByVal lParam$)
  214. Sub cmd_Draw_Click ()
  215.     Dim i%, di%
  216.     pic_Display.Cls
  217.     LoadIndexFromList CurrentSelectedIndex
  218.     For i% = 0 To 7
  219.         di% = DrawIndex(i%, True)
  220.     Next i%
  221. End Sub
  222. ' This function draws the historical chart of an entire index.
  223. ' restart% is set to True to clear the current operation
  224. ' Returns True if the operation is completed, 0 if the function
  225. ' needs to be called again.
  226. ' See article text for additional information on this function
  227. Function DrawIndex% (IndexNum%, restart%)
  228.     Dim CurEntry%
  229.     Dim IVal#
  230.     Dim PrevVal#
  231.     Static StateCurEntry%(7)
  232.     Static StatePrevVal#(7)
  233.     If restart% Then
  234.         StateCurEntry%(IndexNum%) = 1
  235.         If CurrentStateMachine% <> 0 Then
  236.             ' We defined the function to always return
  237.             ' immediately on reset.
  238.             DrawIndex = False
  239.             Exit Function
  240.         End If
  241.     End If
  242.     If IndexList$(IndexNum%, 0) = "" Then
  243.         ' Exit if no entries for this index
  244.         DrawIndex% = True
  245.         Exit Function
  246.     End If
  247.     Select Case CurrentStateMachine%
  248.         Case 0 ' - Non interruptable - VERY SLOW
  249.             For CurEntry% = 1 To period.Columns.Count
  250.                 IVal# = GetIndexVal(IndexNum%, CurEntry%)
  251.                 ' Don't draw the first entry
  252.                 If CurEntry% <> 1 Then pic_Display.Line (CurEntry% - 1, PrevVal#)-(CurEntry%, IVal#), opt_CurIndex(IndexNum%).BackColor
  253.                 PrevVal# = IVal#
  254.             Next CurEntry%
  255.             DrawIndex% = True
  256.         Case 1 To 2 ' Interruptable
  257.             If StateCurEntry%(IndexNum%) > period.Columns.Count Then
  258.                 DrawIndex% = True
  259.                 Exit Function
  260.             End If
  261.             IVal# = GetIndexVal(IndexNum%, StateCurEntry%(IndexNum%))
  262.             ' Don't draw the first entry
  263.             If StateCurEntry%(IndexNum%) <> 1 Then pic_Display.Line (StateCurEntry%(IndexNum%) - 1, StatePrevVal#(IndexNum%))-(StateCurEntry%(IndexNum%), IVal#), opt_CurIndex(IndexNum%).BackColor
  264.             StatePrevVal#(IndexNum%) = IVal#
  265.             StateCurEntry%(IndexNum%) = StateCurEntry%(IndexNum%) + 1
  266.             DrawIndex% = False
  267.     End Select
  268. End Function
  269. Sub Form_Load ()
  270.     Dim col%, usecol&
  271.     Dim rcount%
  272.     Dim di%
  273.     Screen.MousePointer = 11
  274.     ' Initialize the background colors to indicate which
  275.     ' option button corresponds to each index.
  276.     For col% = 0 To 7
  277.         Select Case col%
  278.             Case 0 To 6
  279.                 usecol& = QBColor(col%)
  280.             Case 7  ' We're drawing on a white background
  281.                 usecol& = QBColor(8)
  282.         End Select
  283.         opt_CurIndex(col%).BackColor = usecol&
  284.     Next col%
  285.     mnu_Category_Click (0)  ' Initialize menu
  286.     ' Initialize OLE Automation objects
  287.     Set Sheet = GetObject(app.Path & "\Stocks.XLS")
  288.     Set Companies = Sheet.Range("companies")
  289.     Set period = Sheet.Range("period")
  290.     Set HighRange = Sheet.Range("highprice")
  291.     Set LowRange = Sheet.Range("lowprice")
  292.     Set DataTable = Sheet.Range("StockData")
  293.     ' Now load listbox lst_Companies with a list of all
  294.     ' available companies.  Note that this particular stock
  295.     ' database is entirely ficitional.
  296.     For rcount% = 1 To Companies.Rows.Count
  297.         lst_Companies.AddItem Companies.Cells(rcount%, 1).Text
  298.     Next rcount%
  299.     ' Redimension list to hold all companies if necessary
  300.     ReDim IndexList$(8, Companies.Rows.Count - 1)
  301.     CurrentSelectedIndex% = 0   ' Track current index
  302.     Screen.MousePointer = 0
  303.     StateMachineInput "FormLoaded"
  304. End Sub
  305. ' Retreives the value of an index. It searches through all
  306. ' of the companies that comprise the index and takes the
  307. ' average of their prices (Note that real stock indexes
  308. ' often use different formulas).
  309. Function GetIndexVal# (ByVal IndexNum%, Entrynum%)
  310.     Dim CurVal%
  311.     Dim Comp$
  312.     Dim dl&
  313.     Dim TotalPrice#
  314.     Do
  315.         Comp$ = IndexList$(IndexNum%, CurVal%)
  316.         If Comp$ <> "" Then
  317.             ' Find the offset to the company
  318.             dl& = SendMessageBystring(lst_Companies.hWnd, LB_FINDSTRINGEXACT, -1, Comp$)
  319.             If dl& < 0 Then Exit Do ' Should never happen
  320.         
  321.             ' Now get the data for the specified entry
  322.             TotalPrice# = TotalPrice# + DataTable.Value(dl& + 1, Entrynum%)
  323.             CurVal% = CurVal% + 1
  324.         End If
  325.     Loop While Comp$ <> ""
  326.     If CurVal% > 0 Then GetIndexVal# = TotalPrice# / CurVal%
  327. End Function
  328. ' Retrieves the low and high range for a particular company
  329. Sub GetPeriodLimit (ByVal Company$, LowPrice#, HighPrice#)
  330.     Dim quote As Object
  331.     Dim dl&
  332.     dl& = SendMessageBystring(lst_Companies.hWnd, LB_FINDSTRINGEXACT, -1, Company$)
  333.     If dl& >= 0 Then ' We found it, now select it
  334.         HighPrice# = HighRange.Value(dl& + 1)
  335.         LowPrice# = LowRange.Value(dl& + 1)
  336.     End If
  337. End Sub
  338. ' Loads the company list for an index from the list box
  339. Sub LoadIndexFromList (idxnum%)
  340.     Dim c%, CurEntry%
  341.     For c% = 0 To lst_Companies.ListCount - 1
  342.         If lst_Companies.Selected(c%) Then
  343.             IndexList$(idxnum%, CurEntry%) = lst_Companies.List(c%)
  344.             CurEntry% = CurEntry% + 1
  345.         End If
  346.     Next c%
  347.     ' Clear the rest of the entries
  348.     While CurEntry% < UBound(IndexList$, 1)
  349.         IndexList$(idxnum%, CurEntry%) = ""
  350.         CurEntry% = CurEntry% + 1
  351.     Wend
  352.         
  353. End Sub
  354. ' Loads the company list box from an index list
  355. Sub LoadListFromIndex (idxnum%)
  356.     Dim dl&
  357.     Dim c%
  358.     Dim rng&
  359.     ' First clear all existing selections
  360.     rng& = lst_Companies.ListCount - 1
  361.     rng& = rng * &H10000    ' Shift to high word
  362.     dl& = SendMessageBynum(lst_Companies.hWnd, LB_SELITEMRANGE, 0, rng)
  363.     ' Now loop through the list
  364.     For c% = 0 To UBound(IndexList, 1)
  365.         If IndexList$(idxnum%, c%) = "" Then Exit For' We're done
  366.         dl& = SendMessageBystring(lst_Companies.hWnd, LB_FINDSTRINGEXACT, -1, IndexList(idxnum%, c%))
  367.         If dl& >= 0 Then ' We found it, now select it
  368.             lst_Companies.Selected(dl&) = True
  369.         End If
  370.     Next c%
  371. End Sub
  372. Sub lst_Companies_Click ()
  373.     StateMachineInput "ListClicked"
  374. End Sub
  375. Sub mnu_Category_Click (Index As Integer)
  376.     Dim lbl$
  377.     Dim midx%
  378.     For midx% = 0 To 1  ' Uncheck the other categories
  379.         If midx% <> Index Then mnu_Category(midx%).Checked = False Else mnu_Category(midx%).Checked = True
  380.     Next midx%
  381.     Select Case Index
  382.         Case 0  ' Display is non-interruptable
  383.                 ' This represents the category of task that
  384.                 ' must not allow any user interaction or changes
  385.                 ' by other applications.  It also represents
  386.                 ' non-event driven design.
  387.                 lbl$ = "Non-interruptable: Characteristic of non-event driven design."
  388.                 ' We need a command button to provide any
  389.                 ' sort of decent performance
  390.                 cmd_Draw.Visible = True
  391.         Case 1  ' Display takes place in the background
  392.                 ' Display is retriggered on click on option button
  393.                 cmd_Draw.Visible = False
  394.                 lbl$ = "Background display: Reset on option click"
  395.                 CurrentStateMachine% = 1
  396.         Case 2
  397.                 cmd_Draw.Visible = False
  398.                 lbl$ = "Background display and scale: Reset on option click"
  399.                 CurrentStateMachine% = 2
  400.     End Select
  401.     lbl_DisplayChar = lbl$
  402.     StateMachineInput "MenuClick"
  403. End Sub
  404. Sub opt_CurIndex_Click (Index As Integer)
  405.     ' Exit if no change to index
  406.     If CurrentSelectedIndex% = Index Then Exit Sub
  407.     ' Save previous index information
  408.     LoadIndexFromList CurrentSelectedIndex
  409.     LoadListFromIndex Index
  410.     CurrentSelectedIndex% = Index
  411.     ' Now trigger any background operations that
  412.     ' may be necessary
  413.     StateMachineInput "OptionClicked"
  414. End Sub
  415. ' Sets the scale of the display area to match the period
  416. ' range and the low and high price
  417. ' restart% is set to True to reset the operation
  418. ' Returns -1 if the operation was completed, 0 if the
  419. ' function needs to be called again.
  420. Function SetDisplayScales% (restart%)
  421.     Dim LowPrice#, HighPrice#
  422.     Dim LowestPrice#, HighestPrice#
  423.     Static StateLowestPrice#, StateHighestPrice#
  424.     Static StateC%
  425.     ' The period width is easy: We'll use a coordinate
  426.     ' system corresponding to the number of periods
  427.     ' The vertical ($) axis is scaled from the lowest
  428.     ' price to the highest.  How we do this depends on
  429.     ' the selected Category
  430.     Select Case CurrentStateMachine%
  431.         ' - Non interruptable - VERY SLOW!!!
  432.         Case 0, 1' Machine # 1 does this non-interruptable also
  433.             Dim c%
  434.             For c% = 0 To lst_Companies.ListCount - 1
  435.                 GetPeriodLimit ByVal lst_Companies.List(c%), LowPrice#, HighPrice#
  436.                 If c% = 0 Then
  437.                     LowestPrice# = LowPrice#
  438.                     HighestPrice# = HighPrice#
  439.                 Else
  440.                     If LowPrice# < LowestPrice# Then LowestPrice# = LowPrice#
  441.                     If HighPrice# > HighestPrice# Then HighestPrice# = HighPrice#
  442.                 End If
  443.             Next c%
  444.             pic_Display.Scale (0, HighestPrice#)-(period.Columns.Count, LowestPrice#)
  445.             ' Using this algorithm we are always done
  446.             SetDisplayScales% = True
  447.         Case 2 ' Machine # 2 does this interruptable also
  448.             If restart% Then
  449.                 StateC% = 0
  450.                 SetDisplayScales% = False
  451.                 Exit Function
  452.             End If
  453.             If StateC% > lst_Companies.ListCount - 1 Then
  454.                 pic_Display.Scale (0, StateHighestPrice#)-(period.Columns.Count, StateLowestPrice#)
  455.                 ' Using this algorithm we are always done
  456.                 SetDisplayScales% = True
  457.                 Exit Function
  458.             End If
  459.                 
  460.             GetPeriodLimit ByVal lst_Companies.List(StateC%), LowPrice#, HighPrice#
  461.             If StateC% = 0 Then
  462.                 StateLowestPrice# = LowPrice#
  463.                 StateHighestPrice# = HighPrice#
  464.             Else
  465.                 If LowPrice# < StateLowestPrice# Then StateLowestPrice# = LowPrice#
  466.                 If HighPrice# > StateHighestPrice# Then StateHighestPrice# = HighPrice#
  467.             End If
  468.             StateC% = StateC% + 1
  469.             
  470.     End Select
  471. End Function
  472. ' This is the control function that decides what should
  473. ' be happening at any given time.
  474. ' We're using a string to describe the event for illustration
  475. ' purposes.  A real program would use an integer for efficiency.
  476. ' This is the state machine function that is the heart
  477. ' of the background processing capability.
  478. Sub StateMachineInput (OutsideEvent$)
  479.     Static InternalState%   ' Indicates the current state
  480.     ' 0 - State machine off
  481.     ' 1 - Machine is idle
  482.     ' 2 - State machine is ready to start drawing
  483.     ' 3 - State machine is drawing index InternalIndex%
  484.     ' 4 - State machine is setting scale mode
  485.     Static InternalIndex%   ' Current index being drawn (Machine 1)
  486.     Dim result%
  487.     ' Each of these cases defines a different state
  488.     ' machine.
  489.     Select Case CurrentStateMachine%
  490.         Case 0 ' Non-interruptable.  This is not really
  491.                 ' a state machine - it just performs
  492.                 ' the specified operation immediately
  493.             Select Case OutsideEvent$
  494.                 Case "FormLoaded"
  495.                         result% = SetDisplayScales(True)
  496.                 Case "MenuClicked"
  497.                         ' Turn off the state machine
  498.                         tmr_Background.Enabled = False
  499.                         cmd_Draw_Click
  500.                         InternalState% = 0
  501.                         lbl_DisplayState.Caption = "State Machine Off"
  502.                         pic_Display.Cls
  503.             End Select
  504.         Case 1  ' Background display only (No state 4)
  505.             If OutsideEvent$ = "FormLoaded" Then
  506.                 ' We're not handling display as part of
  507.                 ' the machine at this point
  508.                 result% = SetDisplayScales(True)
  509.             End If
  510.             Select Case InternalState%
  511.                 Case 0  ' Always turn on the machine
  512.                         tmr_Background.Enabled = True
  513.                         InternalState% = 2
  514.                         lbl_DisplayState.Caption = "Start Drawing"
  515.                         pic_Display.Cls
  516.                 Case 1  ' Idle
  517.                     Select Case OutsideEvent$
  518.                         Case "OptionClicked"
  519.                             InternalState% = 2
  520.                             lbl_DisplayState.Caption = "Start Drawing"
  521.                     End Select
  522.                 Case 2  ' Start drawing here
  523.                     InternalIndex% = 0
  524.                     pic_Display.Cls
  525.                     result% = DrawIndex(InternalIndex%, True)
  526.                     InternalState% = 3
  527.                     lbl_DisplayState.Caption = "Drawing in Progress"
  528.                 Case 3
  529.                     Select Case OutsideEvent$
  530.                         Case "OptionClicked" ' Restart
  531.                             InternalState% = 2
  532.                             lbl_DisplayState.Caption = "Start Drawing"
  533.                         Case "Timer"
  534.                             result% = DrawIndex(InternalIndex%, False)
  535.                             If result% Then ' End of index
  536.                                 If InternalIndex% >= 7 Then
  537.                                     InternalState% = 1 ' Goto idle
  538.                                     lbl_DisplayState.Caption = "Idle"
  539.                                 Else
  540.                                     InternalIndex% = InternalIndex + 1
  541.                                     result% = DrawIndex(InternalIndex%, True)
  542.                                 End If
  543.                             End If
  544.                     End Select
  545.             End Select
  546.         Case 2  ' Background display and Scale Mode
  547.             Select Case InternalState%
  548.                 Case 0  ' Always turn on the machine
  549.                         tmr_Background.Enabled = True
  550.                         InternalState% = 4
  551.                         result% = SetDisplayScales(True)
  552.                         lbl_DisplayState.Caption = "Setting Display Scale"
  553.                         pic_Display.Cls
  554.                 Case 1  ' Idle
  555.                     Select Case OutsideEvent$
  556.                         Case "OptionClicked"
  557.                             InternalState% = 2
  558.                             lbl_DisplayState.Caption = "Start Drawing"
  559.                     End Select
  560.                 Case 2  ' Start drawing here
  561.                     InternalIndex% = 0
  562.                     pic_Display.Cls
  563.                     ' We've also changed the drawing algorithm
  564.                     For InternalIndex% = 0 To 7
  565.                         result% = DrawIndex(InternalIndex%, True)
  566.                     Next InternalIndex%
  567.                     InternalState% = 3
  568.                     lbl_DisplayState.Caption = "Drawing in Progress"
  569.                 Case 3
  570.                     Select Case OutsideEvent$
  571.                         Case "OptionClicked" ' Restart
  572.                             InternalState% = 2
  573.                             lbl_DisplayState.Caption = "Start Drawing"
  574.                         Case "Timer"
  575.                             result% = True
  576.                             For InternalIndex% = 0 To 7
  577.                                 ' Look for all of them to finish
  578.                                 result% = result% And DrawIndex(InternalIndex%, False)
  579.                             Next InternalIndex%
  580.                             If result% Then ' End of index
  581.                                 InternalState% = 1 ' Goto idle
  582.                                 lbl_DisplayState.Caption = "Idle"
  583.                             End If
  584.                     End Select
  585.                 Case 4
  586.                     ' Note that the only way to exit this state is
  587.                     ' through completion, or if you change state machines
  588.                     ' using the menu
  589.                     result% = SetDisplayScales(False)
  590.                     
  591.                     If result% Then
  592.                         ' Lets start a drawing operation
  593.                         InternalState% = 2
  594.                         lbl_DisplayState.Caption = "Start Drawing"
  595.                         tmr_Background.Interval = 2
  596.                     End If
  597.             End Select
  598.             
  599.     End Select
  600. End Sub
  601. Sub tmr_Background_Timer ()
  602.     StateMachineInput "Timer"
  603. End Sub
  604.